use shell_escape::unix::escape as shell_escape;
use ssh::error::SshError;
use regex::Regex;





use std::{
    collections::HashMap,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc, Mutex,
    },
    time::{Duration, Instant},
};

use uuid::Uuid;
use lazy_static::lazy_static;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

// 存储执行结果的结构
lazy_static! {
    pub static ref EXECUTIONS: Arc<Mutex<HashMap<String, ExecutionResult>>> = Arc::new(Mutex::new(HashMap::new()));
}

// 执行状态
#[derive(Debug, Clone, PartialEq)]
pub enum ExecutionStatus {
    Running,
    Completed,
    Failed,
    Timeout,
    Interrupted,
}

// 执行结果
#[derive(Debug, Clone)]
pub struct ExecutionResult {
    pub id: String,
    pub status: ExecutionStatus,
    pub exit_code: Option<i32>,
    pub stdout: String,
    pub stderr: String,
}

// 异步执行任务
// 确保AsyncExecution实现Send trait
struct AsyncExecution {
    id: String,
    command: String,
    executor: Arc<Mutex<SshExecutor>>,
    result: Option<Result<ExecutionResult, Box<dyn std::error::Error + Send>>>,
}

unsafe impl Send for AsyncExecution {}

// 为Box<dyn Error>添加Send限制
impl Future for AsyncExecution {
    type Output = Result<ExecutionResult, Box<dyn std::error::Error + Send>>;

    fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
        // 确保我们只执行一次命令
        if self.result.is_none() {
            // 实际执行命令
            let result = {
                let executor = self.executor.lock().unwrap();
                executor.execute_internal(&self.command)
            };
            
            // 更新执行结果
            let execution_result = match EXECUTIONS.lock() {
                Ok(mut executions) => {
                    match executions.get_mut(&self.id) {
                        Some(mut execution_result) => {
                            match result {
                                Ok(ssh_result) => {
                                    println!("SSH result status: {}", ssh_result.status);
                                    println!("Setting execution status to Completed");
                                    execution_result.status = ExecutionStatus::Completed;
                                    execution_result.exit_code = Some(ssh_result.status);
                                    execution_result.stdout = ssh_result.output;
                                    execution_result.stderr = String::new();
                                },
                                Err(e) => {
                                    execution_result.status = ExecutionStatus::Failed;
                                    execution_result.stderr = e.to_string();
                                }
                            }

                            // 由于我们已经通过mut引用修改了execution_result
                            // 所以不需要再次插入，修改已经反映在executions中
                            execution_result.clone()
                        },
                        None => {
                            let error_msg = format!("Execution with id {} not found", self.id);
                            println!("{}", error_msg);
                            return Poll::Ready(Err(Box::new(std::io::Error::new(std::io::ErrorKind::NotFound, error_msg))));
                        }
                    }
                },
                Err(e) => {
                    let error_msg = format!("Failed to lock EXECUTIONS: {}", e);
                    println!("{}", error_msg);
                    return Poll::Ready(Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, error_msg))));
                }
            };

            
            // 无论是否成功，都确保执行结果被存储
        self.result = Some(Ok(execution_result));
        }

        // 使用as_ref()来获取Option中的值的引用，而不是取出并重置为None
        // 克隆整个Option<Result<...>>，然后unwrap它
        // 我们知道result已经被设置，所以可以安全地unwrap它
        Poll::Ready(self.result.take().expect("Result should be set before polling completes"))
    }
}

// 为了兼容异步执行中的使用，重新定义SshResult结构
#[derive(Debug)]
struct SshResult {
    output: String,
    status: i32,
}

// 全局常量，定义最大输出大小 (3MB)
const MAX_OUTPUT: usize = 3 * 1024 * 1024;


pub struct SshExecutor {
    host: String,
    port: u16,
    username: String,
    password: String,
    timeout: Duration,
    interrupted: Arc<AtomicBool>,
}

impl SshExecutor {
    /// 初始化SSH执行器
    pub fn connect(
        host: &str,
        port: u16,
        username: &str,
        password: &str,
        timeout_secs: u64,
    ) -> Result<Self, Box<dyn std::error::Error>> {
        let timeout = Duration::from_secs(timeout_secs);

        let interrupted = Arc::new(AtomicBool::new(false));

        Ok(Self {
            host: host.to_string(),
            port,
            username: username.to_string(),
            password: password.to_string(),
            timeout,
            interrupted,
        })
    }

    /// 设置Ctrl-C中断处理程序
    pub fn setup_interrupt_handler(&mut self) -> Result<(), Box<dyn std::error::Error>> {
        let interrupted_clone = self.interrupted.clone();
        ctrlc::set_handler(move || {
            interrupted_clone.store(true, Ordering::SeqCst);
        })?;
        Ok(())
    }

    /// 执行普通命令（异步）
    pub async fn execute(&mut self, id: Option<String>, command: &str) -> Result<String, Box<dyn std::error::Error>> {
        // 如果没有提供ID，则生成一个新的UUID
        // 生成随机UUID作为默认执行ID
        let execution_id = id.unwrap_or_else(|| Uuid::now_v7().to_string());

        // 创建执行结果并存储
        println!("Creating execution result with id: {}", execution_id);
        match EXECUTIONS.lock() {
            Ok(mut executions) => {
                println!("Successfully locked EXECUTIONS");
                let execution_result = ExecutionResult {
                    id: execution_id.clone(),
                    status: ExecutionStatus::Running,
                    exit_code: None,
                    stdout: String::new(),
                    stderr: String::new(),
                };
                executions.insert(execution_id.clone(), execution_result);
                println!("Successfully inserted execution result with id: {}", execution_id);
                // 验证插入是否成功
                if executions.contains_key(&execution_id) {
                    println!("Verification: execution result with id {} exists", execution_id);
                } else {
                    println!("Verification failed: execution result with id {} not found after insertion", execution_id);
                }
            },
            Err(e) => {
                let error_msg = format!("Failed to lock EXECUTIONS: {}", e);
                println!("{}", error_msg);
                return Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, error_msg)));
            }
        };

        // 创建异步执行任务
        let executor = Arc::new(Mutex::new(self.try_clone()?));
        let async_exec = AsyncExecution {
            id: execution_id.clone(),
            command: command.to_string(),
            executor,
            result: None,
        };
        
        // 启动异步执行（不等待完成）
        tokio::spawn(async_exec);

        // 返回执行ID
        Ok(execution_id)
    }

    /// 以目标用户身份执行命令（异步）
    pub async fn execute_as_user(
        &mut self,
        id: Option<String>,
        command: &str,
        target_user: &str,
        sudo_password: Option<&str>,
    ) -> Result<String, Box<dyn std::error::Error>> {
        let escaped_cmd = shell_escape(command.into());

        // 获取sudo命令路径
        let sudo_path = self.get_sudo_path().await?;

        let sudo_cmd = if let Some(pwd) = sudo_password {
            // 使用echo和管道传递密码，同时保留用户环境变量
            format!(
                "echo '{}' | {} -S -u {} su - {} -c {}",
                pwd.replace("'", "'\\''"), // 转义单引号
                sudo_path, target_user, target_user, escaped_cmd
            )
        } else {
            format!("{} -u {} su - {} -c {}", sudo_path, target_user, target_user, escaped_cmd)
        };

        // 调用普通执行方法
        self.execute(id, &sudo_cmd).await
    }

    /// 获取sudo命令路径
    async fn get_sudo_path(&mut self) -> Result<String, Box<dyn std::error::Error>> {
        // 尝试从环境变量中获取sudo路径
        let which_cmd = "which sudo";
        let execution_id = self.execute(None, which_cmd).await?;
        tokio::time::sleep(Duration::from_millis(500)).await;
        let result = self.get_execution_result(&execution_id).await?;
        let stdout = result.stdout.trim();

        if result.status == ExecutionStatus::Completed && !stdout.is_empty() {
            // 验证找到的路径是否可执行
            let check_cmd = format!("test -x {} && echo 'executable' || echo 'not executable'", &stdout);
            let check_id = self.execute(None, &check_cmd).await?;
            tokio::time::sleep(Duration::from_millis(500)).await;
            let check_result = self.get_execution_result(&check_id).await?;
            let check_stdout = check_result.stdout.trim();

            if check_stdout == "executable" {
                return Ok(stdout.to_string());
            } else {
                return Err(format!("找到sudo路径但不可执行: {}", stdout).into());
            }
        }

        // 如果没有找到，尝试标准路径
        let standard_path = "/usr/bin/sudo";
        let check_cmd = format!("test -x {} && echo 'executable' || echo 'not executable'", standard_path);
        let check_id = self.execute(None, &check_cmd).await?;
        tokio::time::sleep(Duration::from_millis(500)).await;
        let check_result = self.get_execution_result(&check_id).await?;
        let check_stdout = check_result.stdout.trim();

        if check_stdout == "executable" {
            return Ok(standard_path.to_string());
        }

        // 如果所有方法都失败，返回错误
        Err("无法找到sudo命令，请确保目标服务器上已安装sudo并添加到PATH环境变量中".into())
    }

    /// 通过ID获取执行结果
    pub async fn get_execution_result(&self, id: &str) -> Result<ExecutionResult, Box<dyn std::error::Error>> {
        // 检查执行是否存在，最多等待1秒
        let start_time = Instant::now();
        let timeout = Duration::from_secs(1);
        
        loop {
            let executions = EXECUTIONS.lock().map_err(|e| format!("Failed to lock EXECUTIONS: {}", e))?;
            if let Some(execution) = executions.get(id) {
                // 如果已经完成，直接返回结果
                if execution.status != ExecutionStatus::Running {
                    return Ok(execution.clone());
                }
            }
            // 释放锁
            drop(executions);
            
            // 检查是否超时
            if start_time.elapsed() > timeout {
                // 再次检查执行是否存在
                let executions = EXECUTIONS.lock().map_err(|e| format!("Failed to lock EXECUTIONS: {}", e))?;
                if let Some(execution) = executions.get(id) {
                    return Ok(execution.clone());
                } else {
                    return Err(format!("执行ID {} 不存在", id).into());
                }
            }
            
            // 等待一段时间
            tokio::time::sleep(Duration::from_millis(100)).await;
        }
    }

    fn execute_internal(
        &self,
        command: &str
    ) -> Result<SshResult, Box<dyn std::error::Error>> {
        let start_time = Instant::now();

        // 打印SSH库版本信息
        println!("SSH-rs library version: 0.5.0");
        println!("Attempting to connect to {}:{} as {}", self.host, self.port, self.username);
        println!("Timeout: {:?}", self.timeout);

        // 尝试使用原始TCP连接检测服务器是否可达
        println!("Checking if SSH server is reachable...");
        if let Err(e) = self.check_server_reachability() {
            println!("Server unreachable: {}", e);
            return Err(format!("SSH server at {}:{} is unreachable: {}", self.host, self.port, e).into());
        }
        println!("Server is reachable");

        // 创建一个新的会话
        let session_builder = ssh::create_session()
            .username(&self.username)
            .password(&self.password)
            .timeout(Some(self.timeout));

        println!("Session builder created with username and password");

        // 尝试连接，捕获详细错误
        let session = match session_builder.connect(format!("{}:{}", self.host, self.port)) {
            Ok(session) => {
                println!("Successfully connected to SSH server");
                session
            },
            Err(e) => {
                // 打印详细的错误信息
                println!("SSH connection failed: {}", e);
                
                // 尝试根据错误类型提供建议
                match e {
                    SshError::VersionDismatchError { ref our, ref their } => {
                        println!("Version mismatch details:");
                        println!("  Our version: {}", our);
                        println!("  Their version: {}", their);
                        println!("  Suggestion: Check if the SSH server is running and configured correctly");
                        println!("  Suggestion: Verify SSH server compatibility with SSH-rs 0.5.0");
                        println!("  Suggestion: Try using a different SSH library (like openssh) or version");
                        println!("  Suggestion: Check if the SSH server supports SSH protocol version 2");
                        println!("  Suggestion: Verify network connectivity and firewall settings");
                        println!("  Suggestion: Check if the SSH server is sending a valid version string");
                    },
                    _ => {
                        println!("Other SSH error: {:?}", e);
                        // 打印错误的完整类型名称
                        println!("Error type: {}", std::any::type_name::<SshError>());
                        // 打印错误的调试表示
                        println!("Error debug: {:#?}", e);
                    }
                }
                
                return Err(Box::new(e));
            }
        };

        let session = session.run_local();

        let mut session = session;

        // 尝试获取会话的一些属性
        println!("Session created successfully");
        // 注意：根据ssh-rs库的文档，可能没有直接获取版本的方法

        println!("Successfully connected to {}:{}", self.host, self.port);

        // 输出SSH连接状态和配置信息
        println!("SSH connection established");
        println!("Server: {}:{}", self.host, self.port);
        println!("Username: {}", self.username);
        println!("Timeout: {:?}", self.timeout);
        // 注意：无法直接获取SSH版本信息，将在执行命令后检查结果

        let mut exec = session.open_exec()
            .map_err(|e| {
                let error_msg = format!("Failed to open exec channel: {}", e);
                println!("{}: {:?}", error_msg, e);
                e
            })?;

        println!("Exec channel opened successfully");

        // 注意：ssh-rs 0.5.0 版本的 LocalExec 没有 set_timeout 方法
        println!("Command timeout: {:?}", self.timeout);

        // 使用shell包装命令捕获退出码
        // 使用trap捕获退出事件，确保退出码始终被输出
        let wrapped_command = format!(
            r#"sh -c '({}); echo [EXIT_CODE: $?]'"#,
            command.replace('\'', "'\\''")
        );
        let output = match exec.send_command(&wrapped_command) {
            Ok(output) => {
                println!("Command executed successfully");
                let output_str = String::from_utf8_lossy(&output);
                println!("Command output: {}", output_str);
                output.to_vec()
            },
            Err(e) => {
                println!("Failed to send command: {}", e);
                // 尝试获取错误的详细信息
                println!("Error details: {:#?}", e);
                // 打印错误的类型和调试信息
                println!("Error type: {}", std::any::type_name::<SshError>());
                println!("Error debug: {:#?}", e);
                return Err(Box::new(e));
            },
        };

        // 检查输出大小
        let output_str = String::from_utf8_lossy(&output).into_owned();
        let final_output = if output.len() > MAX_OUTPUT {
            let truncated = String::from_utf8_lossy(&output[..MAX_OUTPUT]).into_owned();
            format!(
                "{}\n[输出限制] 输出超过{}字节已被截断",
                truncated, MAX_OUTPUT
            )
        } else {
            output_str
        };

        // 检查超时
        if start_time.elapsed() > self.timeout {
            return Ok(SshResult {
                output: format!(
                    "{}\n[错误] 命令在{}毫秒后超时",
                    final_output,
                    self.timeout.as_millis()
                ),
                status: -1,
            });
        }

        // 检查是否被中断
        if self.interrupted.load(Ordering::SeqCst) {
            return Ok(SshResult {
                output: format!(
                    "{}\n[中断] 命令执行被中断",
                    final_output
                ),
                status: -5,
            });
        }

        // 获取退出状态
        let status = self.get_exit_status(&final_output);
        // 无论退出码如何，只要命令执行完成就设为Completed状态
        Ok(SshResult {
            output: final_output,
            status,
        })
    }

    /// 检查SSH服务器是否可达
    fn check_server_reachability(&self) -> Result<(), Box<dyn std::error::Error>> {
        use std::net::{TcpStream, SocketAddr, IpAddr};

        // 解析主机地址
        let ip_addr: IpAddr = self.host.parse()?;
        let socket_addr = SocketAddr::new(ip_addr, self.port);

        // 建立TCP连接
        let _stream = TcpStream::connect_timeout(
            &socket_addr,
            self.timeout
        )?;
        // 如果能走到这里，说明连接成功
        Ok(())
    }

    /// 辅助函数解析退出状态
    fn get_exit_status(&self, output: &str) -> i32 {
        println!("Parsing exit status for output: {}", output);
        
        // 检查是否包含明确的退出码标记
        if let Some(exit_code) = self.extract_exit_code(output) {
            return exit_code;
        }
        
        //  fallback到原来的逻辑
        if output.contains("not found") {
            println!("Exit status: 127 (command not found)");
            127
        } else if output.contains("Permission denied") {
            println!("Exit status: 126 (permission denied)");
            126
        } else if output.contains("超时") {
            println!("Exit status: -1 (timeout)");
            -1
        } else if output.contains("中断") {
            println!("Exit status: -5 (interrupted)");
            -5
        } else if output.is_empty() {
            println!("Exit status: 0 (empty output)");
            0
        } else if output.contains("invalid") {
            println!("Exit status: 1 (invalid argument)");
            1
        } else {
            println!("Exit status: 0 (default success)");
            0 // 如果无法确定则默认为成功
        }
    }
    
    /// 从输出中提取退出码
    fn extract_exit_code(&self, output: &str) -> Option<i32> {
        // 查找格式为 [EXIT_CODE: X] 的模式，允许前后有空白字符
        let pattern = r#"\s*\[EXIT_CODE:\s*(\d+)\s*\]\s*"#;
        println!("Trying to extract exit code from: {}", output);
        if let Some(captures) = Regex::new(pattern)
            .ok()?
            .captures(output)
        {
            if let Some(exit_code_str) = captures.get(1) {
                if let Ok(exit_code) = exit_code_str.as_str().parse::<i32>() {
                    println!("Extracted exit code: {}", exit_code);
                    return Some(exit_code);
                }
            }
        }
        println!("Failed to extract exit code");
        None
    }

    /// 创建一个新的SshExecutor实例，重用相同的连接信息
    pub fn try_clone(&self) -> Result<Self, Box<dyn std::error::Error>> {
        Ok(Self {
            host: self.host.clone(),
            port: self.port,
            username: self.username.clone(),
            password: self.password.clone(),
            timeout: self.timeout,
            interrupted: self.interrupted.clone(),
        })
    }

    /// 设置中断标志
    pub fn set_interrupted(&self, interrupted: bool) {
        self.interrupted.store(interrupted, Ordering::SeqCst);
    }
}